#include "GGE.h"

GGE::GGE()
{

}

GGE::~GGE()
{
  SDL_FreeSurface ( varGGE_WINDOW_SURFACE );
}


/* ****************************************************************
    Metodo GGE_Init:
    Inicia las librerias graficas del motor. */
void GGE::Init(int initFlag)
{

  switch ( initFlag )
    {
    case 1:
      // "Inicia Video";
      varGGE_INIT_FLAG = 1;
      varGGE_UINT_FLAG = SDL_INIT_VIDEO;
      break;
    case 2:
      // "Inicia el Sonido";
      varGGE_INIT_FLAG = 2;
      varGGE_UINT_FLAG = SDL_INIT_AUDIO;
      break;
    case 3:
      //"Inicia Video y Sonido";
      varGGE_INIT_FLAG = 3;
      varGGE_UINT_FLAG = SDL_INIT_VIDEO | SDL_INIT_AUDIO;
      break;
    case 4:
      // "Inicia ttf";
      varGGE_INIT_FLAG = 4;
      varGGE_UINT_FLAG = SDL_INIT_VIDEO | SDL_INIT_AUDIO;
      break;
    case 5:
      // "Inicia Video y ttf";
      varGGE_INIT_FLAG = 5;
      varGGE_UINT_FLAG = SDL_INIT_VIDEO | SDL_INIT_AUDIO;
      break;
    case 6:
      // "Inicia Sonido y ttf";
      varGGE_INIT_FLAG = 6;
      varGGE_UINT_FLAG = SDL_INIT_VIDEO | SDL_INIT_AUDIO;
      break;
    case 7:
      //"Inicia todo";
      varGGE_INIT_FLAG = 7;
      varGGE_UINT_FLAG = SDL_INIT_EVERYTHING;
      break;
    }

  // Inicia SDL
  if (SDL_Init( varGGE_UINT_FLAG ) < 0)
    {
      cout << SDL_GetError();
      exit(1);
    }

  // Inicia solamente el audio
  if ( varGGE_INIT_FLAG == 2 || varGGE_INIT_FLAG == 3 )
    {
      if (Mix_OpenAudio(44100, AUDIO_S16, 2, 4096))
        {
          cout << "No se ha podido iniciar el sistema de Audio" << endl;
          exit(1);
        }

    }

  // Inicia el audio y las fuentes ttf
  if (  varGGE_INIT_FLAG == 4 ||  varGGE_INIT_FLAG == 5 || varGGE_INIT_FLAG == 6 || varGGE_INIT_FLAG == 7 )
    {
      if (Mix_OpenAudio(44100, AUDIO_S16, 2, 4096))
        {
          cout << "No se ha podido iniciar el sistema de Audio" << endl;
          exit(1);
        }

      if (TTF_Init() != 0)
        {
          cout << "No se ha podido iniciar el sistema de TTF" << endl;
          exit(1);
        }
    }

  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
}

/* ****************************************************************
    Metodo GGE_Exit:
    Sale de la aplicacion.
*/
void GGE::Exit(void)
{
  exit(0);
}

/* ****************************************************************
    Metodo GGE_Mode:
    Establece el modo grafico.
*/
void GGE::Mode( int modeFlag )
{
  varGGE_MODE_FLAG = modeFlag;
}

/* ****************************************************************
    Metodo GGE_Screen:
    Crea la pantalla principal.
*/
void GGE::Screen( int xFlag, int yFlag, int bppFlag, const char appName[255] )
{
  bool renderMode = 0;

  varGGE_WIDTH  = xFlag;
  varGGE_HEIGHT = yFlag;
  varGGE_BPP    = bppFlag;
  SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
  SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
  SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
  SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
  SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16);

  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

  switch ( varGGE_MODE_FLAG )
    {
      // GGE_MODE2D_FULL -> Modo en 2 dimensiones, a pantalla completa.
    case 0:
      if (( varGGE_WINDOW_SURFACE = SDL_SetVideoMode(varGGE_WIDTH,  varGGE_HEIGHT, varGGE_BPP, SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER | SDL_OPENGL | SDL_FULLSCREEN  ) ) == NULL )
        {
          cout << "No se puede crear la superficie 2D a pantalla completa. ¿Estan instaladas las librerias estaticas de SDL/OpenGL en el sistema?";
          exit(0);
        }
      renderMode = 0;
      break;

      // GGE_MODE2D_WIN -> Modo en 2 dimensiones, en modo ventana.
    case 1:
      if (( varGGE_WINDOW_SURFACE = SDL_SetVideoMode( varGGE_WIDTH,varGGE_HEIGHT, varGGE_BPP, SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER | SDL_OPENGL  ) ) == NULL )
        {
          cout << "No se puede crear la superficie 2D en modo ventana. ¿Estan instaladas las librerias estaticas de SDL/OpenGL en el sistema?";
          exit(0);
        }
      renderMode = 0;
      break;

      // GGE_MODE3D_FULL -> Modo en 3 dimensiones, a pantalla completa.
    case 2:
      if (( varGGE_WINDOW_SURFACE = SDL_SetVideoMode(varGGE_WIDTH,  varGGE_HEIGHT, varGGE_BPP, SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER | SDL_OPENGL | SDL_FULLSCREEN    ) ) == NULL )
        {
          cout << "No se puede crear la superficie 3D a pantalla completa. ¿Estan instaladas las librerias estaticas de SDL/OpenGL en el sistema?";
          exit(0);
        }
      renderMode = 1;
      break;

      // GGE_MODE3D_WIN -> Modo en 3 dimensiones, en modo ventana.
    case 3:
      if (( varGGE_WINDOW_SURFACE = SDL_SetVideoMode(varGGE_WIDTH,  varGGE_HEIGHT, varGGE_BPP, SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER | SDL_OPENGL  ) ) == NULL )
        {
          cout << "No se puede crear la superficie 3D en modo ventana. ¿Estan instaladas las librerias estaticas de SDL/OpenGL en el sistema?";
          exit(0);
        }
      renderMode = 1;
      break;
    }

  switch ( renderMode )
    {
    case 0:
      glViewport(0, 0, varGGE_WIDTH,  varGGE_HEIGHT);
      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
      glClearDepth(1.0f);
      glDepthFunc(GL_LESS);
      glEnable(GL_DEPTH);
      glEnable(GL_BLEND);
      glEnable(GL_TEXTURE_2D);
      glShadeModel(GL_SMOOTH);
      glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
      glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho( 0, varGGE_WIDTH,  varGGE_HEIGHT, 0, -1, 1 );
      glMatrixMode(GL_MODELVIEW);
      break;

    case 1:
      glViewport(0, 0,varGGE_WIDTH,  varGGE_HEIGHT);
      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
      glClearDepth(1.0);
      glDepthFunc(GL_LESS);
      glEnable(GL_DEPTH_TEST);
      glShadeModel(GL_SMOOTH);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(45.0f,(GLfloat)varGGE_WIDTH/(GLfloat) varGGE_HEIGHT,0.1f,100.0f);
      glMatrixMode(GL_MODELVIEW);
      break;
    }
  SDL_WM_SetCaption( appName, NULL );

}

/* ****************************************************************
    Metodo GGE_Loop:
    Crea un bucle hasta que se pulse una tecla.
*/
int GGE::Loop(void)
{

  while ((!varGGE_LOOP) && (SDL_WaitEvent(&varGGE_EVENT)))
    {
      switch (varGGE_EVENT.type)
        {
        case SDL_KEYDOWN:
          return 0;
          break;
        case SDL_QUIT:
          return 0;
        }

    }
  return 1;
}

/* ****************************************************************
    Metodo GGE_Flip:
    Refresca los buffers de pantalla.
*/
void GGE::Flip(void)
{
  //  glFlush();

  SDL_GL_SwapBuffers();
}



void GGE::Clear(void)
{
  glClear( GL_COLOR_BUFFER_BIT );
}


void GGE::LoadTTF ( const char * varGGE_UrlTtf, int varSize )
{
  ttfFont = TTF_OpenFont ( varGGE_UrlTtf, varSize );
}

void GGE::Write ( int varX, int varY, const char * varGGE_MSG_STRING )
{

  SDL_Surface * initial;
  ttfColor.r = 255;
  ttfColor.g = 255;
  ttfColor.b = 255;

  GLuint texture;

  initial = TTF_RenderText_Blended( ttfFont, varGGE_MSG_STRING, ttfColor );
  w = initial->w;
  h = initial->h;

  /* Tell GL about our new texture */
  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA,
               GL_UNSIGNED_BYTE, initial->pixels );

  /* GL_NEAREST looks horrible, if scaled... */
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  /* prepare to render our texture */
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, texture);
  glColor3f(1.0f, 1.0f, 1.0f);

  /* Draw a quad at location */
  glBegin(GL_QUADS);
  /* Recall that the origin is in the lower-left corner
  That is why the TexCoords specify different corners
  than the Vertex coors seem to. */

  // Top-left vertex (corner)
  glTexCoord2i( 0, 0 );
  glVertex3f( varX, varY, 0 );

  // Bottom-left vertex (corner)
  glTexCoord2i( 1, 0 );
  glVertex3f( varX + w,varY, 0 );

  // Bottom-right vertex (corner)
  glTexCoord2i( 1, 1 );
  glVertex3f( varX + w, varY + h, 0 );

  // Top-right vertex (corner)
  glTexCoord2i( 0, 1 );
  glVertex3f( varX, varY + h, 0 );


  glEnd();
  /* Bad things happen if we de */
  glFinish();
  /* Clean up */
  SDL_FreeSurface(initial);
  glDeleteTextures(1, &texture);

}

/* **************************************************************** */
